/***************************************************************************
 *   Copyright (C) 2010 by Oleg Goncharov  *
 *   $EMAIL$                           *                          
 *                                                                         *
 *   This file is part of ChessVision.                                     *
 *                                                                         *
 *   ChessVision is free software; you can redistribute it and/or modify   *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef CCHESSMASTER_H
#define CCHESSMASTER_H

#include <list>

#include "cfiguredetector.h"
#include "cchessdetector.h"
#include "vision/ccamtransform.h"
#include "katanavision/ckatanawitheye.h"
#include "katanavision/ckatanasensing.h"
#include "cgnuchessenvelop.h"

/**
	@author Goncharov Oleg <goncharovoi@yandex.ru>
*/
class CChessMaster {
protected:
	struct SMoveDiff {
		int diff;
		Chess::SMove move;
		
		SMoveDiff();
		SMoveDiff(const Chess::SMove& _move, int _diff) : move(_move), diff(_diff) {}
		bool operator<(const SMoveDiff& md) { return diff < md.diff; }
	};
	typedef std::list<SMoveDiff> MoveList;
protected:
// Chesmaster consists of an arm_with_eye, figure and board detectors and chess engine.
	Katana::CKatanaWithEye& arm;
	CikBase& katana;
	CImageSource& src;
	Chess::CChessDetector& det;
	Chess::CFigureDetector& fig;
	Chess::CGnuchessEnvelop& chess_engine;
	
// High-level model of chessmaster world.
	Chess::CPosition pos;
	
// Low-level model of chessmaster world.
	cv::Mat img;
	Chess::CBoardCells cells;
	Chess::CPosition recogn_pos;
	
	int prev_rotation;
	cv::Point3f drop_point;
	// chessboard parameters
	double tablez; // z coordinate of table (in Katana coordinates)
	double fheight;
protected:
	int PossibleMoves(const Chess::CPosition& recogn_pos, int max_diff, MoveList& moves);
	void MoveCoordinatesCorrection(const cv::Point3f& from, cv::Point3f& to);
	void MoveFigure(cv::Point3f from, cv::Point3f to);
	
	bool RecogniseMove(Chess::SMove& move);	
public:
	CChessMaster(Katana::CKatanaWithEye& _arm, Chess::CChessDetector& _det, Chess::CFigureDetector& _fig, Chess::CGnuchessEnvelop& _engine);
	
	void SetFigureParams(double _fheight, double _tablez) { fheight = _fheight; tablez = _tablez; }
	
	void Start();
	void ComputerMove();
	bool HumanMove();
	
	const Chess::CPosition& Position() { return pos; };
	const Chess::CPosition& RecognPosition() { return recogn_pos; };
	const Chess::CBoardCells& RecognBoard() { return cells; };
	const cv::Mat& Image() { return img; };
};

#endif
